package com.ling.zookeeper.zookeeperUtil;

import java.util.List;

import javax.swing.JOptionPane;

import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * 
 * @author yueling
 * zookeeper操作集合
 */
public class ZkUtils {
	private final static Logger logger = LoggerFactory.getLogger(ZkUtils.class);

	/**
	 * zk设置节点值
	 * 
	 * @param node:zookeeper
	 *            node path
	 * @param data:new
	 *            value for update
	 * @param baseZookeeper:zookeeper
	 */
	public static void zkSetNodeData(String node, String data, BaseZookeeper baseZookeeper) {
		try {
			baseZookeeper.setData(node, data.getBytes(), -1);
		} catch (KeeperException |InterruptedException e) {
			logger.error("context", e);
		} 
	}

	/**
	 * zk获取节点数据
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static String zkGetNodeData(String node, BaseZookeeper baseZookeeper) {
		byte[] nodeData = null;
		try {
			nodeData = baseZookeeper.getData(node);
		} catch (KeeperException |InterruptedException e) {
			logger.error("context", e);
		} 
		return new String(nodeData);

	}

	/**
	 * zk删除节点(递归)
	 * 
	 * @param node
	 * @param baseZookeeper
	 */
	public static void zkRmNode(String node, BaseZookeeper baseZookeeper) {

		try {
			baseZookeeper.delete(node);
			logger.info("delete [{}] sucess", node);
		} catch (Exception e) {
			logger.error("context", e);
		}

	}

	/**
	 * 删除节点初始化，参数验证并返回提示信息
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static String zkRmNodeInit(String node, BaseZookeeper baseZookeeper) {
		boolean checkParam = true;
		String result="";
		
		//先格式化一下
		if (node.trim().endsWith("/")) {
			node=node.trim().substring(0, node.trim().length()-1);
		}
		if (!node.startsWith("/")) {
			checkParam=false;
			result=result+"待删除节点路径不正确\n";
		}
		if(!isExist(node, baseZookeeper)){
			checkParam=false;
			result=result+"源节点不存在\n";
			logger.info("源节点不存在");
		}
		if (checkParam) {
			result=result+"开始删除节点:"+node;
			zkRmNode(node,baseZookeeper);
			result=result+"删除结束";
		}else {
			logger.info("检查配置 ：\n\n{}",result);
		}
		return result;
		

	}
	/**
	 * 创建和更新参数化检查并返回结果.如果节点存在提示是否更新；如果节点不存在创建
	 * @param node
	 * @param data
	 * @param baseZookeeper
	 * @return
	 */
	public static String zkCreateNodeInit(String node, String data,BaseZookeeper baseZookeeper) {

		
		boolean checkParam = true;
		String result="";
		
		//先格式化一下
		if (node.trim().endsWith("/")) {
			node=node.trim().substring(0, node.trim().length()-1);
		}
		if (!node.startsWith("/")) {
			checkParam=false;
			result=result+"节点路径不正确\n";
		}
		if (checkParam) {
			if(!isExist(node, baseZookeeper)){
				//创建~
				
				String [] pathArr=node.split("/");
				String path="/";
				for (int i = 1; i < pathArr.length; i++) {
					path=path+pathArr[i];
					if(!isExist(path, baseZookeeper)){
						if (i==pathArr.length-1) {
							zkCreateNode(path, data, baseZookeeper);
						} else {
							zkCreateNode(path, "", baseZookeeper);
						}
						
					}
					path=path+"/";
				}
				logger.info("节点不存在,创建");
			}else {
				//覆盖
				int res=JOptionPane.showConfirmDialog(null, "是否覆盖");
				if (res==JOptionPane.YES_OPTION) {
					zkSetNodeData(node, data, baseZookeeper);
				}
				
			}
		}else {
			logger.info("检查配置 ：\n\n{}",result);
		}
		return result;
		

	}
	/**
	 * 查询参数验证并返回结果
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static String zkQueryNodeInit(String node, BaseZookeeper baseZookeeper) {

		
		boolean checkParam = true;
		String result="";
		
		//先格式化一下
		if (node.trim().endsWith("/")) {
			node=node.trim().substring(0, node.trim().length()-1);
		}
		if (!node.startsWith("/")) {
			checkParam=false;
			result=result+"节点路径不正确\n";
		}
		if(!isExist(node, baseZookeeper)){
			checkParam=false;
			result=result+"源节点不存在\n";
			logger.info("源节点不存在");
		}
		if (checkParam) {
			result=result+node+"="+zkGetNodeData(node,baseZookeeper);
			result=result+"查询结束";
		}else {
			logger.info("检查配置 ：\n\n{}",result);
		}
		return result;
		

	}
	/**
	 * zk创建单个的节点
	 * 
	 * @param node
	 * @param baseZookeeper
	 */
	public static String zkCreateNode(String node, String data, BaseZookeeper baseZookeeper) {
		String returnPath = null;
		try {
			returnPath = baseZookeeper.createNode(node, data.getBytes());
		} catch (KeeperException |InterruptedException e) {
			logger.error("context", e);
		} 

		return returnPath;

	}

	/**
	 * zk复制节点(包括子节点)
	 * 
	 * 限制：同一个zk实例上的复制
	 * 
	 * @param node
	 * @param destNode
	 * @param baseZookeeper
	 */
	public static void zkCopyNodes(String node, String destNode, BaseZookeeper baseZookeeper) {
		zkCopyNodes(node, destNode, baseZookeeper, baseZookeeper);
	}

	/**
	 * zk复制节点(包括子节点)
	 * 
	 * 在同一个zk实例、不同实例之间、不同机器之间复制
	 * 
	 * @param node
	 * @param destNode
	 * @param baseZookeeper
	 * @param destZookeeper
	 */
	public static void zkCopyNodes(String node, String destNode, BaseZookeeper baseZookeeper,
			BaseZookeeper destZookeeper) {
		zkCreateNode(destNode, zkGetNodeData(node, baseZookeeper), destZookeeper);
		if (zkHasChildNode(node, baseZookeeper)) {
			List<String> list = zkGetChildNode(node, baseZookeeper);
			for (int i = 0; i < list.size(); i++) {
				zkCopyNodes(node + "/" + list.get(i), destNode + "/" + list.get(i), baseZookeeper, destZookeeper);
			}
		}
	}

	/**
	 * zk复制节点包括子节点
	 * 
	 * 在同一个zk实例、不同实例之间、不同机器之间
	 * 
	 * @param node
	 * @param destNode
	 * @param baseZookeeper
	 * @param destZookeeper
	 */
	public static String zkCopyNodesInit(String node,String destNode,BaseZookeeper baseZookeeper,BaseZookeeper destZookeeper) {
		
		/*
		 * 检查node在baseZookeeper上是否存在
		 * 检查destNode在destZookeeper上是否存在
		 * 
		 * 如果目录存在
		 * 		覆盖：先删除
		 * 		取消：终止操作（保险）
		 *		合并：逐级合并（有风险，挖个坑先不实现……不服你来) 
		 * 
		 */
		
		
		//没有合适的api如何……自己写，从根遍历
		//是否是合法路径  是否以/开始  startwith
		//是否包含非法字符 删除末尾空格和/
		//
	
		
		//传入路径和值 返回是否存在的结果
		
		boolean checkParam = true;
		String result="";
		
		//先格式化一下
		if (node.trim().endsWith("/")) {
			node=node.trim().substring(0, node.trim().length()-2);
		}
		if (destNode.trim().endsWith("/")) {
			destNode=destNode.trim().substring(0, destNode.trim().length()-2);
		}
		if (!node.startsWith("/")) {
			checkParam=false;
			result=result+"源节点路径不正确\n";
		}
		if (!destNode.startsWith("/")) {
			checkParam=false;
			result=result+"目标节点路径不正确\n";
		}
		
		
		if(!isExist(node, baseZookeeper)){
			checkParam=false;
			result=result+"源节点不存在\n";
			logger.info("源节点不存在");
		}
		
		if(isExist(destNode, destZookeeper,1)){
			if(isExist(destNode, destZookeeper)){
				checkParam=false;
				result=result+"目标节点已经存在\n";
				logger.info("目标节点已经存在");
			}
		}else {
			checkParam=false;
			result=result+"目标节点的父节点不存在\n";
			logger.info("目标节点的父节点不存在");
		}
		if (checkParam) {
			result=result+"开始复制***\n<br>";
			zkCopyNodes(node, destNode, baseZookeeper, destZookeeper);
			result=result+"结束复制***\n请检查目标目录:【"+destNode+"】";
		}else {
			logger.info("检查配置 ：\n\n{}",result);
		}
		return result;
	}

	/**
	 * 目录下是否包含指定的节点
	 * 
	 * 如：/usr/ 下是否包含local
	 * 
	 * @param nodePath
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static boolean isContains(String nodePath, String node, BaseZookeeper baseZookeeper) {
		System.out.println(nodePath+"\t"+node+"\t"+zkGetChildNode(nodePath, baseZookeeper).contains(node));
		return zkGetChildNode(nodePath, baseZookeeper).contains(node);
	}

	/**
	 * 指定路径的节点是否存在
	 * 
	 * 如：/usr/local 是否存在
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static boolean isExist(String node, BaseZookeeper baseZookeeper) {
		return isExist(node,baseZookeeper,0);
	}
	/**
	 * 指定路径的节点是否存在
	 * 
	 * 如：/usr/local 是否存在
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @param offset
	 * @return
	 */
	public static boolean isExist(String node, BaseZookeeper baseZookeeper,int offset) {
		String[] splitNode = node.split("/");
		String root = "/";
		boolean result = true;
		for (int i = 1; i < splitNode.length-offset; i++) {
			if (!isContains(root, splitNode[i], baseZookeeper)) {
				result = false;
				break;
			}
			root = (root + "/" + splitNode[i]).replace("//", "/");
		}
		return result;
	}


	/**
	 * zk获取某个zk节点的下属的子节点
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static List<String> zkGetChildNode(String node, BaseZookeeper baseZookeeper) {
		List<String> child = null;
		try {
			child = baseZookeeper.getChildren(node);
		} catch (KeeperException |InterruptedException e) {
			logger.error("context", e);
		} 

		return child;

	}

	/**
	 * zk路径下是否有子节点
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static boolean zkHasChildNode(String node, BaseZookeeper baseZookeeper) {
		List<String> child = null;
		try {
			child = baseZookeeper.getChildren(node);
			if (child.isEmpty()) {
				return false;
			}
		} catch (KeeperException |InterruptedException e) {
			logger.error("context", e);
		} 
		return true;

	}

	/**
	 * 从zk中获取某个节点的json并转存为jsonObject
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */

	public static JsonObject getZkNodedaToJsonObject(String node, BaseZookeeper baseZookeeper) {
		String json = zkGetNodeData(node, baseZookeeper);
		logger.info("getZkNodeDataToJsonArray:path {} \n json String :{}", node, json);
		JsonParser parser = new JsonParser(); // 创建JSON解析器
		JsonObject jsonObject = (JsonObject) parser.parse(json);
		return jsonObject;

	}

	/**
	 * 从zk中获取某节点的json，并转存为JsonArray
	 * 
	 * @param node
	 * @param baseZookeeper
	 * @return
	 */
	public static JsonArray getZkNodeDataToJsonArray(String node, BaseZookeeper baseZookeeper) {
		String json = zkGetNodeData(node, baseZookeeper);
		logger.info("getZkNodeDataToJsonArray:path {} \n json String :{}", node, json);
		JsonParser parser = new JsonParser(); // 创建JSON解析器
		JsonArray jsonArray = (JsonArray) parser.parse(json);
		return jsonArray;
	}
}
